<?php

namespace App\Providers;

use App\Models\Common\Area\Area;
use App\Models\Common\Channel\Channel;
use App\Models\Plane\Airports\Airport;
use App\Models\Plane\Airports\AirportsGeoManager;
use App\Models\Plane\Cities\PlaneCity as PlaneCitiesModel;
use App\Models\Plane\Flight\FlightCabin;
use App\Models\Task\SnapTasks\SnapTask;
use App\Models\Train\Stations\StationGeoManager;
use App\Models\Train\Stations\TrainStation;
use App\Models\Train\TrainIssues\TrainIssue;
use App\Models\Train\TrainPoints\TrainPoint;
use App\Models\Train\Trains\Train;
use App\Models\Train\TrainSeat\TrainSeat;
use App\Models\Train\TrainSeatInfo\TrainSeatInfo;
use App\Models\Train\TrainTripInfo\TrainCheckingPort;
use App\Models\Train\TrainTripInfo\TrainExitingPort;
use App\Models\Train\TrainTripInfo\TrainTripInfo;
use App\Models\User\Repositories\CacheUser;
use App\Models\User\User;
use App\Models\User\WechatMiniAppUser;
use App\Models\User\WechatOfficialUser;
use App\Observers\AreaObserver;
use App\Observers\ChannelObserver;
use App\Observers\Plane\AirportsObserver;
use App\Observers\Plane\FlightCabinObserver;
use App\Observers\Plane\PlaneCitiesObserver;
use App\Observers\Train\Port\CheckingPortObserver;
use App\Observers\Train\Port\ExitingPortObserver;
use App\Observers\Train\Snap\SnapTaskObserver;
use App\Observers\Train\TrainIssueObserver;
use App\Observers\Train\TrainPointObserver;
use App\Observers\Train\TrainSeatInfoObserver;
use App\Observers\Train\TrainSeatObserver;
use App\Observers\Train\TrainsObserver;
use App\Observers\Train\TrainStationObserver;
use App\Observers\Train\TrainTripInfoObserver;
use App\Observers\UserObserver;
use App\Observers\WechatMiniAppUserObserver;
use App\Observers\WechatOfficialUserObserver;
use App\Trip\Crypt\Aes;
use App\Trip\IdentityCode\IdentityCode;
use App\Trip\Notify\Sms\Sms;
use App\Trip\Plane\PlaneCities;
use App\Trip\Plane\PlaneCompany;
use App\Trip\Train\Providers\PiaoChi\User\Login as PiaoChiUserLogin;
use App\Trip\Train\Providers\PiaoChi\User\User as PiaoChiUser;
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
use Exception;
use Godruoyi\Snowflake\LaravelSequenceResolver;
use Godruoyi\Snowflake\Snowflake;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {

        // 注册 user_cache
        $this->registerUserCache();
        // 注册 aes
        $this->registerAES();
        // 注册 雪花id
        $this->registerSnowFlake();
        // 注册piaochi user
        $this->registerPiaoChiUser();

        // 注册geo
        $this->registerGeo();

        // 注册 航空公司 --
        $this->registerPlaneRelationSeed();

        // 注册短信
        $this->app->singleton('sms', function () {
            return new Sms();
        });

        if ($this->app->isLocal()) {
            $this->app->register(IdeHelperServiceProvider::class);
            $this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
            $this->app->register(TelescopeServiceProvider::class);
        }
    }

    private function registerUserCache()
    {
        $this->app->singleton('user_cache', function () {
            return new CacheUser();
        });

    }

    private function registerAES()
    {
        $this->app->singleton('aes', function () {
            return new Aes();
        });

    }

    protected function registerSnowFlake()
    {
        $this->app->singleton('snowflake', function () {
            return (new Snowflake())
                ->setStartTimeStamp(strtotime('2022-02-02') * 1000)
                ->setSequenceResolver(
                    new LaravelSequenceResolver($this->app->get('cache')->store()
                    ));
        });
    }

    protected function registerPiaoChiUser()
    {
        $this->app->singleton('piao_chi_user', function () {
            return new PiaoChiUser();
        });

        $this->app->singleton('piao_chi_user_login', function () {
            return new PiaoChiUserLogin(new PiaoChiUser());
        });
    }

    private function registerGeo()
    {
        $this->app->singleton('station_geo', function () {
            return new StationGeoManager();
        });

        $this->app->singleton('airports_geo', function () {
            return new AirportsGeoManager();
        });
    }

    private function registerPlaneRelationSeed()
    {
        $this->app->singleton('plane_company_seed', function () {
            return new PlaneCompany();
        });

        $this->app->singleton('plane_city_seed', function () {
            return new PlaneCities();
        });
    }

    // 拓展验证器

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Schema::defaultStringLength(191);
        // 验证器拓展
        $this->extendValidator();
        // 自定义观察器
        $this->bootObserver();
    }

    protected function extendValidator()
    {
        // 手机号验证
        Validator::extend('phone', function ($attribute, $value, $parameters) {
            return preg_match('/^1[3456789][0-9]{9}$/', $value);
        });

        // 乘客证件号验证
        Validator::extend('passengers_identify_number', function ($attribute, $value, $parameters, \Illuminate\Validation\Validator $validator) {
            $idxs       = explode(".", $attribute);
            $count_type = count($idxs); // 1  参数名，2 *.参数名，3 x.*.参数名
            if (empty($parameters)) {
                throw new Exception("必须要验证乘客证件类型");
            }

            switch ($count_type) {
                case 1:
                    $type_value = Arr::get($validator->attributes(), $parameters[0]);
                    break;
                case 2:
                    $idx        = $idxs[0];
                    $type_value = Arr::get($validator->attributes()[$idx], $parameters[0]);
                    break;
                case 3:
                    $prefix     = $idxs[0];
                    $idx        = $idxs[1];
                    $type_param = Str::replace("*", $idx, $parameters[0]);
                    $type_value = Arr::get($validator->attributes()[$prefix][$idx], $type_param);
                    break;
                default:
                    throw new Exception("暂不支持该数据结构类型的验证");
            }
            if ($type_value == 1) {
                $ident = new IdentityCode($value);
                return $ident->isValid();
            } else {
                // 暂时没有规则
                return true;
            }

        });

        // 身份证号验证
        Validator::extend('identify_number', function ($attribute, $value, $parameters) {
            $ident = new IdentityCode($value);
            return $ident->isValid();
        });
    }

    // 注册雪花id 实现

    protected function bootObserver()
    {
        // 用户观察者
        User::observe(UserObserver::class);
        Area::observe(AreaObserver::class);
        Channel::observe(ChannelObserver::class);
//        Train::observe(TrainsObserver::class);
//        SnapTask::observe(SnapTaskObserver::class);
//        TrainSeat::observe(TrainSeatObserver::class);
//        TrainIssue::observe(TrainIssueObserver::class);
//        TrainPoint::observe(TrainPointObserver::class);
//        TrainStation::observe(TrainStationObserver::class);
//        TrainTripInfo::observe(TrainTripInfoObserver::class);
//        TrainSeatInfo::observe(TrainSeatInfoObserver::class);
//        TrainExitingPort::observe(ExitingPortObserver::class);
//        TrainCheckingPort::observe(CheckingPortObserver::class);
        WechatMiniAppUser::observe(WechatMiniAppUserObserver::class);
        WechatOfficialUser::observe(WechatOfficialUserObserver::class);
//        Airport::observe(AirportsObserver::class);
//        PlaneCitiesModel::observe(PlaneCitiesObserver::class);
//        FlightCabin::observe(FlightCabinObserver::class);
    }
}
